﻿using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.Resources;
using System.Globalization;
using System.Reflection;
using EnvDTE;
using Microsoft.SharePoint;

namespace SPVisualDev
{
    public partial class DialogFeatureEditor : Form
    {
        private SPVisualDev.Connect m_addin_instance;
        private FeatureManager m_feature_manager;
        private Dictionary<Guid, string> m_features_in_project = new Dictionary<Guid, string>();

        private ProjectItem m_feature_folder;
        private PropSheetMainInfo m_main_info;
        private string m_resource_editor_last_used_file;
        private string DefaultResourceFile
        {
            get
            {
                if (txtPageGeneral_DefaultResourceFile.Text == "<Feature local>")
                    return Common.C_LOCAL_RESOURCE_IDENTIFIER;
                else
                    return txtPageGeneral_DefaultResourceFile.Text;
            }
            set
            {
                if (string.Compare(value, Common.C_LOCAL_RESOURCE_IDENTIFIER, true) == 0)
                {
                    txtPageGeneral_DefaultResourceFile.Text = "<Feature local>";
                }
                else
                {
                    txtPageGeneral_DefaultResourceFile.Text = value;
                }
            }
        }

        private string FeatureID
        {
            get { return txtFeatureID.Text; }
            set { txtFeatureID.Text = value; }
        }

        public DialogFeatureEditor(ProjectItem FeatureFolder, SPVisualDev.Connect AddinInstance)
        {
            InitializeComponent();

            m_addin_instance = AddinInstance;

            this.FormClosing += new FormClosingEventHandler(Dialog_FormClosing);
            this.Load += new EventHandler(Dialog_Load);

            this.lstPageElements_ContainingElements.SelectedIndexChanged += new EventHandler(lstPageElements_ContainingElements_SelectedIndexChanged);

            this.lstPageElements_AvailableElements.MouseDoubleClick += new MouseEventHandler(lstPageElements_AvailableElements_MouseDoubleClick);

            this.grdPageElements_Properties.PropertyValueChanged += new PropertyValueChangedEventHandler(PropertyGrid_PropertyValueChanged);
            this.grdPageElements_Properties.SelectedGridItemChanged += new SelectedGridItemChangedEventHandler(PropertyGrid_SelectedGridItemChanged);
            this.grdPageElements_Properties.SelectedObjectsChanged += new EventHandler(grdPageElements_Properties_SelectedObjectsChanged);

            this.grdPageGeneral_MainInfo.PropertyValueChanged += new PropertyValueChangedEventHandler(PropertyGrid_PropertyValueChanged);
            this.grdPageGeneral_MainInfo.SelectedGridItemChanged += new SelectedGridItemChangedEventHandler(PropertyGrid_SelectedGridItemChanged);

            m_feature_folder = FeatureFolder;
            this.Text = m_feature_folder.Name;

            m_feature_manager = new FeatureManager(FeatureFolder);

        }

        private void Dialog_Load(object sender, EventArgs e)
        {
            m_feature_manager.ReadContent();


            lstPageElements_ContainingElements.Sorted = true;
            lstPageElements_AvailableElements.Sorted = true;

            btnPageElements_ImportContentType.Visible = false;

            string xmldoc_feature_file_path = Common.GetProjectItemPath(m_feature_folder.ProjectItems.Item("Feature.xml"));

            txtFeatureID.Text = m_feature_manager.FeatureID;
            this.DefaultResourceFile = m_feature_manager.FeatureDefaultResourceFile;


            m_main_info = new PropSheetMainInfo(this.DefaultResourceFile, m_feature_folder, null);
            m_main_info.Title.RawString = m_feature_manager.FeatureTitle;
            m_main_info.Description.RawString = m_feature_manager.FeatureDescription;

            grdPageGeneral_MainInfo.PropertySort = PropertySort.NoSort;
            grdPageGeneral_MainInfo.SelectedObject = m_main_info;

            MoveSplitter(grdPageGeneral_MainInfo, 150);

            grdPageElements_Properties.PropertySort = PropertySort.NoSort;

            string feature_scope = m_feature_manager.FeatureScope;
            m_main_info.Scope = SPFeatureScope.ScopeInvalid;
            if (!string.IsNullOrEmpty(feature_scope))
            {
                SPFeatureScope scope = SPFeatureScope.ScopeInvalid;
                try
                {
                    scope = (SPFeatureScope)Enum.Parse(typeof(SPFeatureScope), feature_scope, true);
                }
                catch { }

                if (scope != SPFeatureScope.ScopeInvalid)
                {
                    m_main_info.Scope = scope;
                }
            }

            m_main_info.Version = m_feature_manager.FeatureVersion;
            m_main_info.Hidden = m_feature_manager.FeatureHidden;
            m_main_info.EventReceiver = (m_feature_manager.FeatureEventReceiverAssembly != "");

            if (this.FeatureID == string.Empty)
            {
                this.FeatureID = Guid.NewGuid().ToString("D").ToUpper();
            }

            m_main_info.HasUnsavedResourceChanges = false;

            foreach (ElementInfo el_info in m_feature_manager.GetAllElements())
            {
                switch (el_info.ElementName)
                {
                    case "ListTemplate":
                        PropSheetListTemplate prop_sheet_LT = new PropSheetListTemplate(this.DefaultResourceFile, m_feature_folder, el_info.XmlElementNode);
                        prop_sheet_LT.SetNewSheetFlag(false);
                        prop_sheet_LT.ElementFileName = el_info.ElementFileName;
                        prop_sheet_LT.ElementInfo = el_info;
                        AddElementToContainingList(prop_sheet_LT);
                        break;

                    case "ContentType":
                        PropSheetContentType prop_sheet_CT = new PropSheetContentType(this.DefaultResourceFile, m_feature_folder, el_info.XmlElementNode);
                        prop_sheet_CT.SetNewSheetFlag(false);
                        prop_sheet_CT.ElementFileName = el_info.ElementFileName;
                        prop_sheet_CT.ElementInfo = el_info;
                        AddElementToContainingList(prop_sheet_CT);
                        break;

                    case "Module":
                        PropSheetModule prop_sheet_module = new PropSheetModule(this.DefaultResourceFile, m_feature_folder, el_info.XmlElementNode);
                        prop_sheet_module.ElementFileName = el_info.ElementFileName;
                        prop_sheet_module.ElementInfo = el_info;
                        AddElementToContainingList(prop_sheet_module);
                        break;

                    case "ListInstance":
                        PropSheetListInstance prop_sheet_list_instance = new PropSheetListInstance(this.DefaultResourceFile, m_feature_folder, el_info.XmlElementNode);
                        prop_sheet_list_instance.ElementFileName = el_info.ElementFileName;
                        prop_sheet_list_instance.ElementInfo = el_info;
                        AddElementToContainingList(prop_sheet_list_instance);
                        break;

                    case "CustomAction":
                        PropSheetCustomAction prop_sheet_ca = new PropSheetCustomAction(this.DefaultResourceFile, m_feature_folder, el_info.XmlElementNode);
                        prop_sheet_ca.ElementFileName = el_info.ElementFileName;
                        prop_sheet_ca.ElementInfo = el_info;
                        AddElementToContainingList(prop_sheet_ca);
                        break;

                    case "Field":
                        PropSheetField prop_sheet_field = new PropSheetField(this.DefaultResourceFile, m_feature_folder, el_info.XmlElementNode);
                        prop_sheet_field.ElementFileName = el_info.ElementFileName;
                        prop_sheet_field.ElementInfo = el_info;
                        AddElementToContainingList(prop_sheet_field);
                        break;
                }
            }

            EnumAllFeaturesInProject();
            foreach (KeyValuePair<Guid, string> kvp in m_features_in_project)
            {
                cboPageActivationDep_FeatureToAdd.Items.Add(kvp.Value + ":" + kvp.Key.ToString().ToUpper());
            }

            foreach (Guid gid in m_feature_manager.ActivationDependencies)
            {
                if (m_features_in_project.ContainsKey(gid))
                {
                    lstPageActivationDep_List.Items.Add(m_features_in_project[gid] + ":" + gid.ToString("D").ToUpper());
                }
                else
                {
                    lstPageActivationDep_List.Items.Add("(feature not in project):" + gid.ToString("D").ToUpper());
                }
            }

            
            txtPageGeneral_DefaultResourceFile.Leave += new EventHandler(txtPageGeneral_DefaultResourceFile_Leave);
            txtPageGeneral_DefaultResourceFile.KeyDown += new KeyEventHandler(txtPageGeneral_DefaultResourceFile_KeyDown);
            
            
            btnPageElements_PickResource.Enabled = false;
        }

        private void EnumAllFeaturesInProject()
        {
            m_features_in_project = new Dictionary<Guid, string>();
            ProjectItem features_root = m_feature_folder.Collection.Parent as ProjectItem;
            foreach (ProjectItem item in features_root.ProjectItems)
            {
                if (item.Kind != Constants.vsProjectItemKindPhysicalFolder)
                    continue;

                string path = Common.GetProjectItemPath(item);
                if (!File.Exists(path + "\\Feature.xml"))
                    continue;

                try
                {
                    XmlDocument xmldoc = new XmlDocument();
                    xmldoc.Load(path + "\\Feature.xml");
                    string id = Common.GetXmlAttribute(xmldoc.DocumentElement, "ID");
                    m_features_in_project.Add(new Guid(id.Trim().ToUpper()), item.Name);
                }
                catch { }
            }
        }

        private void txtPageGeneral_DefaultResourceFile_KeyDown(object sender, KeyEventArgs e)
        {
            try
            {
                if (e.KeyCode == Keys.Enter)
                {
                    this.tabPageGeneral.Select();
                }
            }
            catch (Exception ex)
            {
                DialogError.ShowError(ex, false);
            }
        }

        private void txtPageGeneral_DefaultResourceFile_Leave(object sender, EventArgs e)
        {
            try
            {
                if (HasPendingResourceChanges())
                {
                    string msg = "All unsaved resource changes will be discarded if changing the default resource file. Do you want to save them?";

                    DialogResult result = MessageBox.Show(msg, "Prompt", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1);

                    if (result == DialogResult.None || result == DialogResult.Cancel)
                    {
                        return;
                    }
                    else if (result == DialogResult.Yes)
                    {
                        SaveAllPendingResourceChanges();
                    }
                }

                this.DefaultResourceFile = txtPageGeneral_DefaultResourceFile.Text;

                InvalidateResourceCache();

                grdPageElements_Properties.Refresh();
                grdPageGeneral_MainInfo.Refresh();

            }
            catch (Exception ex)
            {
                DialogError.ShowError(ex, false);
            }
        }

        private void Dialog_FormClosing(object sender, FormClosingEventArgs e)
        {
            try
            {
                if (this.DialogResult != DialogResult.OK)
                {
                    if (MessageBox.Show("Discard changes?", "Prompt", MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button2) != DialogResult.OK)
                    {
                        e.Cancel = true;
                        return;
                    }
                }

                if (this.DialogResult != DialogResult.OK)
                    return;

                bool isValid = ValidateForm(false);
                if (!isValid)
                {
                    e.Cancel = true;
                    return;
                }

                SaveFeatureChanges();

            }
            catch (Exception ex)
            {
                DialogError.ShowError(ex, false);
            }
        }

        private void PropertyGrid_SelectedGridItemChanged(object sender, SelectedGridItemChangedEventArgs e)
        {
            try
            {
                RefreshPickResourceButtonStatus(sender as PropertyGrid);

            }
            catch (Exception ex)
            {
                DialogError.ShowError(ex, false);
            }
        }

        private void RefreshPickResourceButtonStatus(PropertyGrid grid)
        {
            if (grid.SelectedGridItem == null)
            {
                btnPageElements_PickResource.Enabled = false;
                btnPageGeneral_PickResource.Enabled = false;

                return;
            }

            if (grid.SelectedGridItem.Value is ResourceStringContainer)
            {
                btnPageElements_PickResource.Enabled = true;
                btnPageGeneral_PickResource.Enabled = true;
            }
            else
            {
                btnPageElements_PickResource.Enabled = false;
                btnPageGeneral_PickResource.Enabled = false;
            }
        }

        private void MoveSplitter(PropertyGrid propertyGrid, int x)
        {
            object propertyGridView = typeof(PropertyGrid).InvokeMember("gridView", BindingFlags.GetField | BindingFlags.NonPublic | BindingFlags.Instance, null, propertyGrid, null);
            propertyGridView.GetType().InvokeMember("MoveSplitterTo", BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance, null, propertyGridView, new object[] { x });
        }

        private void grdPageElements_Properties_SelectedObjectsChanged(object sender, EventArgs e)
        {
            try
            {
                btnPageElements_ImportContentType.Visible = false;

                lstPageElements_ContainingElements.Refresh();

                if (grdPageElements_Properties.SelectedObject == null)
                    return;

                if (grdPageElements_Properties.SelectedObject.GetType() == typeof(PropSheetContentType))
                {
                    btnPageElements_ImportContentType.Visible = true;
                }
            }
            catch (Exception ex)
            {
                DialogError.ShowError(ex, false);
            }
        }

        private void PropertyGrid_PropertyValueChanged(object sender, PropertyValueChangedEventArgs e)
        {
            try
            {
                PropertyGrid grid = sender as PropertyGrid;

                if (e.ChangedItem.PropertyDescriptor.PropertyType == typeof(ResourceStringContainer))
                {
                    ResourceStringContainer old_value = e.OldValue as ResourceStringContainer;
                    ResourceStringContainer new_value = e.ChangedItem.Value as ResourceStringContainer;

                    if (ResourceHelper.IsResourceString(old_value.RawString))
                    {
                        string msg = "Changing the resource key will discard all changes made since last save for this resource key. Do you want to change it?";
                        if (MessageBox.Show(msg, "Prompt", MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button2) == DialogResult.OK)
                        {
                            ResourceStringContainer res_container = new ResourceStringContainer(new_value.RawString, this.DefaultResourceFile, m_feature_folder);
                            e.ChangedItem.PropertyDescriptor.SetValue(grid.SelectedObject, res_container);
                        }
                        else
                        {
                            e.ChangedItem.PropertyDescriptor.SetValue(grid.SelectedObject, old_value);
                        }

                        grid.Refresh();

                    }
                }

                if (grid.Name == "grdPageElements_Properties")
                {
                    if (lstPageElements_ContainingElements.SelectedIndex != -1)
                        lstPageElements_ContainingElements.Items[lstPageElements_ContainingElements.SelectedIndex] = grid.SelectedObject;

                    lstPageElements_ContainingElements.Refresh();
                }

            }
            catch (Exception ex)
            {
                DialogError.ShowError(ex, false);
            }
        }

        private void lstPageElements_AvailableElements_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            try
            {
                btnPageElements_AddFeatureElement_Click(sender, e);

            }
            catch (Exception ex)
            {
                DialogError.ShowError(ex, false);
            }
        }

        public void AddElementToContainingList(object PropertySheet)
        {
            lstPageElements_ContainingElements.Items.Add(PropertySheet);
        }

        private void SaveFeatureChanges()
        {

            string skip_files = Common.GetUserSettingsKey(m_feature_folder.ContainingProject, "SkipFilesPushDown");

            if (HasPendingResourceChanges())
                SaveAllPendingResourceChanges();

            foreach (object elment in lstPageElements_ContainingElements.Items)
            {

                IPropertySheet sheet = elment as IPropertySheet;

                if (sheet.ElementFileNameHasChanged)
                {
                    m_feature_manager.RemoveElement(sheet.ElementInfo.ID, false);
                    m_feature_manager.AddElement(sheet.ElementFileName, sheet.PropXmlNode.OuterXml);
                }

                XmlElement xel = sheet.PropXmlNode;

                string element_name = xel.LocalName;
                if (sheet.ElementInfo.New)
                {
                    if (element_name == "ListTemplate")
                    {
                        PropSheetListTemplate obj = elment as PropSheetListTemplate;
                        bool b = AddListTemplateFiles(obj, obj.OriginalType.ToString());
                        if (!b)
                            return;
                    }
                    else if (element_name == "ContentType")
                    {
                        PropSheetContentType obj = elment as PropSheetContentType;
                        AddContentTypeFiles(obj);
                    }
                    else if (element_name == "Module")
                    {
                        PropSheetModule prop_sheet_module = elment as PropSheetModule;

                        ProjectItem module_folder = null;
                        string folder_name = Common.FilterIllegalCharsInFileName(GetElementFolderName(prop_sheet_module.Name));
                        try
                        {
                            module_folder = m_feature_folder.ProjectItems.AddFolder(folder_name, Constants.vsProjectItemKindPhysicalFolder);
                        }
                        catch
                        {
                            MessageBox.Show("Feature already contains an element folder named '" + folder_name + "'. Element files will be skipped.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        }

                        if (prop_sheet_module.SubType == "WebPart")
                            AddWebPartFiles(prop_sheet_module, module_folder);
                        else if (prop_sheet_module.SubType == "MasterPage")
                            AddMasterPage(prop_sheet_module, module_folder);
                    }
                }

            }


            m_feature_manager.FeatureTitle = m_main_info.Title.RawString;
            m_feature_manager.FeatureDescription = m_main_info.Description.RawString;
            m_feature_manager.FeatureID = this.FeatureID;
            m_feature_manager.FeatureScope = m_main_info.Scope.ToString();
            m_feature_manager.FeatureDefaultResourceFile = this.DefaultResourceFile;
            m_feature_manager.FeatureHidden = m_main_info.Hidden;
            m_feature_manager.FeatureVersion = m_main_info.Version;

            //Configure feature event receiver information
            if (!m_main_info.EventReceiver)
            {
                if (m_feature_manager.FeatureEventReceiverAssembly != "")
                {
                    if (MessageBox.Show("Do you want to remove the feature event receiver registration for this feature?", "Prompt", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button2) == DialogResult.Yes)
                    {
                        m_feature_manager.FeatureEventReceiverAssembly = "";
                        m_feature_manager.FeatureEventReceiverClass = "";
                    }
                }
            }
            else
            {

                if (m_feature_manager.FeatureEventReceiverAssembly == "")
                {
                    try
                    {
                        bool canContinue = true;
                        string asm_name = string.Empty;

                        //Build the project so we can extract assembly information.
                        try
                        {
                            m_addin_instance.BuildProject(m_feature_folder.ContainingProject, true, false);
                        }
                        catch(Exception ex)
                        {
                            DialogError.ShowError(ex, "Project could not be built. Creation of feature event receiver will be skipped.", false);

                            canContinue = false;
                        }

                        if (canContinue)
                        {
                            try
                            {
                                asm_name = Common.GetTargetBuildAssemblyName(m_feature_folder.ContainingProject, true);
                            }
                            catch(Exception ex)
                            {
                                DialogError.ShowError(ex, "Failed to get assembly name. Creation of feature event receiver will be skipped.", false);
                                canContinue = false;
                            }

                            if (canContinue)
                            {
                                bool b = (asm_name.ToLower().IndexOf("publickeytoken") != -1);
                                if (b)
                                    b = (asm_name.ToLower().IndexOf("publickeytoken=null") == -1);

                                if (Common.GetProjectGlobalConfigKey(m_feature_folder.ContainingProject, "AssemblyBuildType") != "GAC" || !b)
                                {
                                    MessageBox.Show("Event receivers can not run if the assembly doesn't have a strong name and the project build type is not GAC. Please change it in artifact configuration menu for correct behavior. Event receivers will not be created for this feature.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                                    canContinue = false;
                                }
                            }
                        }

                        if (canContinue)
                        {
                            string safe_folder_name = Common.FilterIllegalCharsInFileName(m_feature_folder.Name);
                            string code_ns = m_feature_folder.ContainingProject.Properties.Item("RootNamespace").Value.ToString();
                            if (string.IsNullOrEmpty(Common.GetProjectGlobalConfigKey(m_feature_folder.ContainingProject, "EventRecNSsuffix")))
                                code_ns += "." + Common.C_PROJECT_EVENT_RECEIVER_CODE_PATH + "." + safe_folder_name;
                            else
                                code_ns += "." + Common.GetProjectGlobalConfigKey(m_feature_folder.ContainingProject, "EventRecNSsuffix") + "." + safe_folder_name;

                            ProjectItem event_receiver_folder;
                            if (Common.GetProjectGlobalConfigKey(m_feature_folder.ContainingProject, "EventRecCodeInFeatureFolder") == "True")
                                event_receiver_folder = m_feature_folder;
                            else
                            {
                                string suffix = Common.GetProjectGlobalConfigKey(m_feature_folder.ContainingProject, "EventRecNSsuffix");
                                if (string.IsNullOrEmpty(suffix))
                                    suffix = Common.C_PROJECT_EVENT_RECEIVER_CODE_PATH;

                                event_receiver_folder = Common.CreateProjectItemPath(m_feature_folder.ContainingProject, suffix.Replace(".", "\\") + "\\" + safe_folder_name);
                            }

                            ProjectItem i = null;
                            try
                            {
                                i = event_receiver_folder.ProjectItems.Item("FeatureEventReceiver.cs");
                            }
                            catch { }

                            if (i != null)
                            {
                                if (MessageBox.Show(string.Format("There is already a feature event receiver in folder {0} called {1}. Do you want to replace the existing file?", Common.GetProjectItemPath(event_receiver_folder), i.Name), "Prompt", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button2) == DialogResult.Yes)
                                {
                                    i.Delete();
                                    i = null;
                                }
                            }

                            if (i == null)
                            {
                                string template_path = ((EnvDTE80.Solution2)m_feature_folder.DTE.Solution).GetProjectItemTemplate("Feature event receiver.zip", "csproj");
                                event_receiver_folder.ProjectItems.AddFromTemplate(template_path, "FeatureEventReceiver.cs");

                                ProjectItem item = event_receiver_folder.ProjectItems.Item("FeatureEventReceiver.cs");
                                item.Document.ReplaceText("$trackingid$", FeatureID, 0);
                                Common.SetNamespaceInCodeFile(ref item, code_ns);
                                item.Document.Close(vsSaveChanges.vsSaveChangesYes);



                                //m_feature_manager.FeatureEventReceiverAssembly = "(value will be updated when feature is installed by the addin)";
                                //m_feature_manager.FeatureEventReceiverClass = "(value will be updated when feature is installed by the addin)";

                                m_feature_manager.FeatureEventReceiverAssembly = asm_name;
                                m_feature_manager.FeatureEventReceiverClass = code_ns + ".FeatureEventReceiver";
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show("Failed to set feature event receiver files. " + ex.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }

                }
            }

            m_feature_manager.WriteContent(false);

            return;
        }

        private void lstPageElements_ContainingElements_SelectedIndexChanged(object sender, EventArgs e)
        {
            try
            {
                if (lstPageElements_ContainingElements.SelectedItem == null)
                {
                    grdPageElements_Properties.SelectedObject = null;
                    grdPageElements_Properties.Refresh();
                    return;
                }

                bool shouldMoveSplitter = (grdPageElements_Properties.SelectedObject == null);

                grdPageElements_Properties.SelectedObject = lstPageElements_ContainingElements.SelectedItem;
                grdPageElements_Properties.Refresh();

                if (shouldMoveSplitter)
                    MoveSplitter(grdPageElements_Properties, 150);

                grdPageElements_Properties.Focus();

            }
            catch (Exception ex)
            {
                DialogError.ShowError(ex, false);
            }
        }

        private void btnPageElements_AddFeatureElement_Click(object sender, EventArgs e)
        {
            try
            {
                if (lstPageElements_AvailableElements.SelectedItem == null)
                    return;

                ElementInfo el_info;
                string element = lstPageElements_AvailableElements.SelectedItem.ToString();
                switch (element)
                {
                    case "List template":

                        el_info = m_feature_manager.AddElement(null, "<ListTemplate/>");

                        PropSheetListTemplate prop_sheet_lt = new PropSheetListTemplate(this.DefaultResourceFile, m_feature_folder, el_info.XmlElementNode);

                        prop_sheet_lt.ElementFileName = el_info.ElementFileName;
                        prop_sheet_lt.ElementInfo = el_info;
                        prop_sheet_lt.Type = int.Parse(FindNextUniqeListDefinitionId(10001).ToString());
                        prop_sheet_lt.SecurityBits = 11;
                        prop_sheet_lt.Name = "";
                        prop_sheet_lt.SetNewSheetFlag(true);

                        grdPageElements_Properties.SelectedObject = prop_sheet_lt;
                        lstPageElements_ContainingElements.SelectedIndex = lstPageElements_ContainingElements.Items.Add(prop_sheet_lt);

                        break;

                    case "Content type":
                        el_info = m_feature_manager.AddElement(null, "<ContentType><FieldRefs xmlns=\"" + Common.C_MS_SHAREPOINT_XMLNS + "\"/></ContentType>");

                        PropSheetContentType prop_sheet_ct = new PropSheetContentType(this.DefaultResourceFile, m_feature_folder, el_info.XmlElementNode);
                        prop_sheet_ct.ElementFileName = el_info.ElementFileName;
                        prop_sheet_ct.ElementInfo = el_info;
                        prop_sheet_ct.SetNewSheetFlag(true);

                        lstPageElements_ContainingElements.SelectedIndex = lstPageElements_ContainingElements.Items.Add(prop_sheet_ct);

                        break;

                    case "Module":
                        el_info = m_feature_manager.AddElement(null, "<Module/>");

                        PropSheetModule prop_sheet_module = new PropSheetModule(this.DefaultResourceFile, m_feature_folder, el_info.XmlElementNode);

                        prop_sheet_module.ElementFileName = el_info.ElementFileName;
                        prop_sheet_module.ElementInfo = el_info;
                        prop_sheet_module.Name = Common.GetSafeName(Common.GetProjectItemPath(m_feature_folder), "Module");
                        prop_sheet_module.Path = prop_sheet_module.Name;

                        lstPageElements_ContainingElements.SelectedIndex = lstPageElements_ContainingElements.Items.Add(prop_sheet_module);
                        break;

                    case "List instance":
                        el_info = m_feature_manager.AddElement(null, "<ListInstance/>");

                        PropSheetListInstance prop_sheet_list_instance = new PropSheetListInstance(this.DefaultResourceFile, m_feature_folder, el_info.XmlElementNode);

                        prop_sheet_list_instance.ElementFileName = el_info.ElementFileName;
                        prop_sheet_list_instance.ElementInfo = el_info;
                        prop_sheet_list_instance.FeatureId = m_feature_manager.FeatureID;

                        lstPageElements_ContainingElements.SelectedIndex = lstPageElements_ContainingElements.Items.Add(prop_sheet_list_instance);
                        break;

                    case "Custom action":
                        el_info = m_feature_manager.AddElement(null, "<CustomAction/>");

                        PropSheetCustomAction prop_sheet_ca = new PropSheetCustomAction(this.DefaultResourceFile, m_feature_folder, el_info.XmlElementNode);

                        prop_sheet_ca.ElementFileName = el_info.ElementFileName;
                        prop_sheet_ca.ElementInfo = el_info;

                        lstPageElements_ContainingElements.SelectedIndex = lstPageElements_ContainingElements.Items.Add(prop_sheet_ca);
                        break;

                    case "Web part":
                        el_info = m_feature_manager.AddElement(null, "<Module/>");

                        PropSheetModule prop_sheet_webpart = new PropSheetModule(this.DefaultResourceFile, m_feature_folder, el_info.XmlElementNode);

                        prop_sheet_webpart.ElementFileName = el_info.ElementFileName;
                        prop_sheet_webpart.ElementInfo = el_info;
                        prop_sheet_webpart.Name = Common.GetSafeName(Common.GetProjectItemPath(m_feature_folder), "WebPart");
                        prop_sheet_webpart.Path = prop_sheet_webpart.Name;
                        prop_sheet_webpart.Url.RawString = "_catalogs/wp";
                        prop_sheet_webpart.SubType = "WebPart";

                        lstPageElements_ContainingElements.SelectedIndex = lstPageElements_ContainingElements.Items.Add(prop_sheet_webpart);
                        break;

                    case "Master page":
                        el_info = m_feature_manager.AddElement(null, "<Module/>");

                        PropSheetModule prop_sheet_master_page = new PropSheetModule(this.DefaultResourceFile, m_feature_folder, el_info.XmlElementNode);

                        prop_sheet_master_page.ElementFileName = el_info.ElementFileName;
                        prop_sheet_master_page.ElementInfo = el_info;
                        prop_sheet_master_page.Name = Common.GetSafeName(Common.GetProjectItemPath(m_feature_folder), "MasterPage");
                        prop_sheet_master_page.Path = prop_sheet_master_page.Name;
                        prop_sheet_master_page.Url.RawString = "_catalogs/masterpage";
                        prop_sheet_master_page.SubType = "MasterPage";

                        lstPageElements_ContainingElements.SelectedIndex = lstPageElements_ContainingElements.Items.Add(prop_sheet_master_page);
                        break;

                    case "Field":
                        el_info = m_feature_manager.AddElement(null, "<Field/>");

                        PropSheetField prop_sheet_field = new PropSheetField(
                            this.DefaultResourceFile,
                            m_feature_folder,
                            el_info.XmlElementNode);

                        prop_sheet_field.ElementFileName = el_info.ElementFileName;
                        prop_sheet_field.ElementInfo = el_info;
                        prop_sheet_field.ID = Guid.NewGuid().ToString("B");
                        prop_sheet_field.Type = "Text";

                        lstPageElements_ContainingElements.SelectedIndex = lstPageElements_ContainingElements.Items.Add(prop_sheet_field);
                        break;
                }

            }
            catch (Exception ex)
            {
                DialogError.ShowError(ex, false);
            }
        }

        private void btnPageElements_RemoveFeatureElement_Click(object sender, EventArgs e)
        {
            try
            {
                if (lstPageElements_ContainingElements.SelectedItems.Count == 0)
                    return;


                DialogResult res = MessageBox.Show(string.Format("Caution! Element '{0}' will immediately be deleted from this feature. Do you want to proceed?", lstPageElements_ContainingElements.SelectedItem.ToString()), "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2);
                if (res != DialogResult.Yes)
                    return;



                IPropertySheet selected_item = lstPageElements_ContainingElements.SelectedItem as IPropertySheet;

                if (selected_item.ElementInfo.ElementName == "Module" ||
                    selected_item.ElementInfo.ElementName == "ListTemplate")
                {
                    XmlElement el = selected_item.ElementInfo.XmlElementNode;

                    if (el.GetAttribute("Name") != "")
                    {
                        ProjectItem item = null;
                        try
                        {
                            item = m_feature_folder.ProjectItems.Item(el.GetAttribute("Name"));
                        }
                        catch { }

                        if (item != null)
                        {
                            if (item.Kind == Constants.vsProjectItemKindPhysicalFolder)
                            {
                                m_feature_manager.RemoveFeatureXMLElementFile(item.Name, true);
                                m_feature_manager.CommitChangesToFeatureXML();

                                item.Delete();

                            }
                        }
                    }

                    if (selected_item.ElementInfo.ElementName == "ListTemplate")
                    {
                        if (el.GetAttribute("Type") != "")
                            m_feature_manager.RemoveListEventRegistration(int.Parse(el.GetAttribute("Type")), true);
                    }
                }

                m_feature_manager.RemoveElement(selected_item.ElementInfo.ID, true);

                lstPageElements_ContainingElements.Items.RemoveAt(lstPageElements_ContainingElements.SelectedIndex);

            }
            catch (Exception ex)
            {
                DialogError.ShowError(ex, false);
            }
        }

        private bool AddListTemplateFiles(PropSheetListTemplate element, string TemplateToUse)
        {
            string templates_path = element.OriginalType.TemplateFilesPath;
            if (string.IsNullOrEmpty(templates_path))
                throw new Exception("List templates path can not be empty.");
            if (!Directory.Exists(templates_path))
                throw new Exception("Can not find templates path '" + templates_path + "'");

            if (string.IsNullOrEmpty(element.Name))
            {
                MessageBox.Show("List template type " + element.Type.ToString() + " name can not be null. Operation is canceled.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }

            string safe_element_name = Common.FilterIllegalCharsInFileName(GetElementFolderName(element.Name));
            if (CheckIfElementFolderExists(safe_element_name))
            {
                MessageBox.Show("An element folder with the name '" + safe_element_name + "' already exists in this feature or in the same path but excluded from the project. Operation is canceled.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }

            ProjectItem list_files_dir = null;
            if (!string.IsNullOrEmpty(templates_path))
            {
                list_files_dir = m_feature_folder.ProjectItems.AddFolder(safe_element_name, Constants.vsProjectItemKindPhysicalFolder);
                string[] files = System.IO.Directory.GetFiles(templates_path);
                foreach (string file in files)
                {
                    list_files_dir.ProjectItems.AddFromFileCopy(file);
                }
            }
            else
            {
                list_files_dir = m_feature_folder.ProjectItems.AddFolder(safe_element_name, Constants.vsProjectItemKindPhysicalFolder);
            }

            if (element.EventReceivers)
            {
                string safe_feature_folder_name = Common.FilterIllegalCharsInFileName(m_feature_folder.Name);
                string code_ns = m_feature_folder.ContainingProject.Properties.Item("RootNamespace").Value.ToString();
                if (string.IsNullOrEmpty(Common.GetProjectGlobalConfigKey(m_feature_folder.ContainingProject, "EventRecNSsuffix")))
                    code_ns += "." + Common.C_PROJECT_EVENT_RECEIVER_CODE_PATH + "." + safe_feature_folder_name;
                else
                    code_ns += "." + Common.GetProjectGlobalConfigKey(m_feature_folder.ContainingProject, "EventRecNSsuffix") + "." + safe_feature_folder_name;

                ProjectItem event_receiver_folder;
                if (Common.GetProjectGlobalConfigKey(m_feature_folder.ContainingProject, "EventRecCodeInFeatureFolder") == "True")
                    event_receiver_folder = list_files_dir;
                else
                {
                    string suffix = Common.GetProjectGlobalConfigKey(m_feature_folder.ContainingProject, "EventRecNSsuffix");
                    if (string.IsNullOrEmpty(suffix))
                        suffix = Common.C_PROJECT_EVENT_RECEIVER_CODE_PATH;

                    event_receiver_folder = Common.CreateProjectItemPath(m_feature_folder.ContainingProject, suffix.Replace(".", "\\") + "\\" + safe_feature_folder_name);
                }

                ProjectItem i = null;
                try
                {
                    event_receiver_folder.ProjectItems.Item(safe_element_name + "_ItemEventReceiver.cs");
                }
                catch { }

                if (i != null)
                {
                    if (MessageBox.Show(string.Format("There is already an item event receiver in folder {0} called {1}. Do you want to replace the existing file?", Common.GetProjectItemPath(event_receiver_folder), i.Name), "Prompt", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation) == DialogResult.Yes)
                    {
                        i.Delete();
                        i = null;
                    }
                    else
                    {
                        return false;
                    }
                }

                try
                {
                    event_receiver_folder.ProjectItems.Item(safe_element_name + "_ListEventReceiver.cs");
                }
                catch { }

                if (i != null)
                {
                    if (MessageBox.Show(string.Format("There is already a list event receiver in folder {0} called {1}. Do you want to replace the existing file?", Common.GetProjectItemPath(event_receiver_folder), i.Name), "Prompt", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation) == DialogResult.Yes)
                    {
                        i.Delete();
                        i = null;
                    }
                    else
                    {
                        return false;
                    }
                }


                if (i == null)
                {
                    //Check source control
                    /*
                    bool isEvReceiverPathUnderSCC = event_receiver_folder.DTE.SourceControl.IsItemUnderSCC(Common.GetProjectItemPath(event_receiver_folder));
                    if (isEvReceiverPathUnderSCC)
                        event_receiver_folder.DTE.SourceControl.CheckOutItem(Common.GetProjectItemPath(event_receiver_folder));
                    */

                    try
                    {
                        string template_path = ((EnvDTE80.Solution2)m_feature_folder.DTE.Solution).GetProjectItemTemplate("Item event receiver.zip", "csproj");
                        event_receiver_folder.ProjectItems.AddFromTemplate(template_path, safe_element_name + "_ItemEventReceiver.cs");

                        ProjectItem item = event_receiver_folder.ProjectItems.Item(safe_element_name + "_ItemEventReceiver.cs");
                        item.Document.ReplaceText("$trackingid$", new Guid(FeatureID).ToString("N").ToUpper() + "_" + element.Name, 0);
                        Common.SetNamespaceInCodeFile(ref item, code_ns);
                        item.Document.Close(vsSaveChanges.vsSaveChangesYes);


                        template_path = ((EnvDTE80.Solution2)m_feature_folder.DTE.Solution).GetProjectItemTemplate("List event receiver.zip", "csproj");
                        event_receiver_folder.ProjectItems.AddFromTemplate(template_path, safe_element_name + "_ListEventReceiver.cs");

                        item = event_receiver_folder.ProjectItems.Item(safe_element_name + "_ListEventReceiver.cs");
                        item.Document.ReplaceText("$trackingid$", new Guid(FeatureID).ToString("N").ToUpper() + "_" + element.Name, 0);
                        Common.SetNamespaceInCodeFile(ref item, code_ns);
                        item.Document.Close(vsSaveChanges.vsSaveChangesYes);
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show("Failed to set event receiver files. " + ex.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        return false;
                    }
                }

            }

            return true;
        }

        private bool CheckIfElementFolderExists(string FolderName)
        {
            ProjectItem folder = null;
            try
            {
                folder = m_feature_folder.ProjectItems.Item(FolderName);
                return true;
            }
            catch
            {
            }

            if (System.IO.Directory.Exists(Common.GetProjectItemPath(m_feature_folder) + "\\" + FolderName))
                return true;

            return false;
        }

        private void AddContentTypeFiles(PropSheetContentType element)
        {
            //string safe_content_type_name = Common.FilterIllegalCharsInFileName(GetElementFolderName(element.Name.RawString));
            string name = element.Name.GetValue(null);
            if (string.IsNullOrEmpty(name))
                name = element.ElementInfo.ElementName + element.ElementInfo.ID.ToString();

            string safe_content_type_name = Common.FilterIllegalCharsInFileName(name);

            if (element.EventReceivers)
            {
                string safe_folder_name = Common.FilterIllegalCharsInFileName(m_feature_folder.Name);

                string code_ns = m_feature_folder.ContainingProject.Properties.Item("RootNamespace").Value.ToString();
                if (string.IsNullOrEmpty(Common.GetProjectGlobalConfigKey(m_feature_folder.ContainingProject, "EventRecNSsuffix")))
                    code_ns += "." + Common.C_PROJECT_EVENT_RECEIVER_CODE_PATH + "." + safe_folder_name;
                else
                    code_ns += "." + Common.GetProjectGlobalConfigKey(m_feature_folder.ContainingProject, "EventRecNSsuffix") + "." + safe_folder_name;

                ProjectItem event_receiver_folder;
                if (Common.GetProjectGlobalConfigKey(m_feature_folder.ContainingProject, "EventRecCodeInFeatureFolder") == "True")
                    event_receiver_folder = m_feature_folder;
                else
                {
                    string suffix = Common.GetProjectGlobalConfigKey(m_feature_folder.ContainingProject, "EventRecNSsuffix");
                    if (string.IsNullOrEmpty(suffix))
                        suffix = Common.C_PROJECT_EVENT_RECEIVER_CODE_PATH;

                    event_receiver_folder = Common.CreateProjectItemPath(m_feature_folder.ContainingProject, suffix.Replace(".", "\\") + "\\" + safe_folder_name);
                }

                ProjectItem i = null;
                try
                {
                    event_receiver_folder.ProjectItems.Item(safe_content_type_name + "_ItemEventReceiver.cs");
                }
                catch { }

                if (i != null)
                {
                    if (MessageBox.Show(string.Format("There is already an item event receiver in folder {0} called {1}. Do you want to replace the existing file?", Common.GetProjectItemPath(event_receiver_folder), i.Name), "Prompt", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation) == DialogResult.Yes)
                    {
                        i.Delete();
                        i = null;
                    }
                    else
                    {
                        return;
                    }
                }

                try
                {
                    event_receiver_folder.ProjectItems.Item(safe_content_type_name + "_ListEventReceiver.cs");
                }
                catch { }

                if (i != null)
                {
                    if (MessageBox.Show(string.Format("There is already a list event receiver in folder {0} called {1}. Do you want to replace the existing file?", Common.GetProjectItemPath(event_receiver_folder), i.Name), "Prompt", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation) == DialogResult.Yes)
                    {
                        i.Delete();
                        i = null;
                    }
                    else
                    {
                        return;
                    }
                }

                if (i == null)
                {
                    try
                    {
                        string template_path = ((EnvDTE80.Solution2)m_feature_folder.DTE.Solution).GetProjectItemTemplate("Item event receiver.zip", "csproj");
                        event_receiver_folder.ProjectItems.AddFromTemplate(template_path, safe_content_type_name + "_ItemEventReceiver.cs");

                        ProjectItem item = event_receiver_folder.ProjectItems.Item(safe_content_type_name + "_ItemEventReceiver.cs");
                        item.Document.ReplaceText("$trackingid$", element.ID, 0);
                        Common.SetNamespaceInCodeFile(ref item, code_ns);
                        item.Document.Close(vsSaveChanges.vsSaveChangesYes);

                        template_path = ((EnvDTE80.Solution2)m_feature_folder.DTE.Solution).GetProjectItemTemplate("List event receiver.zip", "csproj");
                        event_receiver_folder.ProjectItems.AddFromTemplate(template_path, safe_content_type_name + "_ListEventReceiver.cs");

                        item = event_receiver_folder.ProjectItems.Item(safe_content_type_name + "_ListEventReceiver.cs");
                        item.Document.ReplaceText("$trackingid$", element.ID, 0);
                        Common.SetNamespaceInCodeFile(ref item, code_ns);
                        item.Document.Close(vsSaveChanges.vsSaveChangesYes);
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show("Failed to set event receiver files. " + ex.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        return;
                    }
                }
            }

        }

        private void AddWebPartFiles(PropSheetModule element, ProjectItem element_folder)
        {
            string code_ns = m_feature_folder.ContainingProject.Properties.Item("RootNamespace").Value.ToString();
            string feature_prefix = Common.FilterIllegalCharsInFileName(m_feature_folder.Name);
            if (string.IsNullOrEmpty(Common.GetProjectGlobalConfigKey(m_feature_folder.ContainingProject, "WebPartsNSsuffix")))
                code_ns += ".UI.Webparts." + feature_prefix;
            else
                code_ns += "." + Common.GetProjectGlobalConfigKey(m_feature_folder.ContainingProject, "WebPartsNSsuffix") + "." + feature_prefix;

            ProjectItem web_part_code_folder;
            if (Common.GetProjectGlobalConfigKey(m_feature_folder.ContainingProject, "WPCodeInFeatureFolder") == "True")
                web_part_code_folder = element_folder;
            else
                web_part_code_folder = Common.CreateProjectItemPath(element_folder.ContainingProject,
                    Common.GetProjectGlobalConfigKey(element_folder.ContainingProject, "WebPartsNSsuffix").Replace(".", "\\") + "\\" + feature_prefix);

            try
            {
                string template_path;
                ProjectItem item;

                template_path = ((EnvDTE80.Solution2)m_feature_folder.DTE.Solution).GetProjectItemTemplate("SPVisualDev Web Part.zip", "csproj");
                web_part_code_folder.ProjectItems.AddFromTemplate(template_path, GetElementFolderName(element.Name));

                item = web_part_code_folder.ProjectItems.Item(element.Name + ".cs");
                Common.SetNamespaceInCodeFile(ref item, code_ns);
                item.Document.Close(vsSaveChanges.vsSaveChangesYes);

                template_path = ((EnvDTE80.Solution2)m_feature_folder.DTE.Solution).GetProjectItemTemplate("SPVisualDev Web Part definition (webpart).zip", "csproj");
                element_folder.ProjectItems.AddFromTemplate(template_path, GetElementFolderName(element.Name));

                item = element_folder.ProjectItems.Item(element.Name + ".webpart");
                item.Document.ReplaceText("$namespace$", code_ns, 0);

                string asm_name;
                if (Common.GetProjectGlobalConfigKey(m_feature_folder.ContainingProject, "AssemblyBuildType") == "GAC")
                {
                    asm_name = Common.GetTargetBuildAssemblyName(m_feature_folder.ContainingProject, false);
                    if (asm_name.IndexOf("PublicKeyToke=null") != -1)
                        MessageBox.Show("The assembly is not signed with a public key token.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);

                }
                else
                {
                    asm_name = m_feature_folder.ContainingProject.Properties.Item("AssemblyName").Value.ToString();
                }

                item.Document.ReplaceText("$typename$", code_ns + "." + Common.FilterIllegalCharsInFileName(GetElementFolderName(element.Name)) + ", " + asm_name, 0);
                item.Document.ReplaceText("$assembly$", asm_name, 0);
                item.Name = element.Name + ".webpart";
                item.Document.Close(vsSaveChanges.vsSaveChangesYes);

            }
            catch (Exception ex)
            {
                MessageBox.Show("Failed to set web part files. " + ex.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

        }

        private void AddMasterPage(PropSheetModule element, ProjectItem element_folder)
        {
            try
            {
                string template_path = ((EnvDTE80.Solution2)m_feature_folder.DTE.Solution).GetProjectItemTemplate("Master page (minimal no code behind).zip", "csproj");
                element_folder.ProjectItems.AddFromTemplate(template_path, GetElementFolderName(element.Name));
            }
            catch (Exception ex)
            {
                MessageBox.Show("Failed to add master page. " + ex.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
        }

        private void btnPageGeneral_GenerateID_Click(object sender, EventArgs e)
        {
            try
            {
                if (MessageBox.Show("Do you want to generate a new feature ID?", "Prompt", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
                {
                    txtFeatureID.Text = Guid.NewGuid().ToString("D").ToUpper();
                }

            }
            catch (Exception ex)
            {
                DialogError.ShowError(ex, false);
            }
        }

        private void btnOK_Click(object sender, EventArgs e)
        {
            try
            {
                //if (m_main_info.EventReceiver)
                //{
                //    if (Common.GetProjectGlobalConfigKey(m_feature_folder.ContainingProject, "AssemblyBuildType") != "GAC")
                //        MessageBox.Show("Event receivers can not run if the project build type is not GAC. Please change it in artifact configuration menu for correct behavior.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                //}

                this.DialogResult = DialogResult.OK;
                this.Close();

            }
            catch (Exception ex)
            {
                DialogError.ShowError(ex, false);
            }
        }

        private int FindNextUniqeListDefinitionId(int Start)
        {
            bool b = true;

            while (b)
            {
                bool found = false;
                foreach (ElementInfo info in m_feature_manager.GetAllElements())
                {
                    if (info.ElementFileName == "ListTemplate")
                    {
                        string type = info.XmlElementNode.GetAttribute("Type");
                        if (!string.IsNullOrEmpty(type))
                        {
                            if (int.Parse(type) == Start)
                            {
                                found = true;
                                break;
                            }
                        }
                    }
                }

                if (!found)
                {
                    b = false;
                }
                else
                {
                    Start++;
                }
            }

            return Start;
        }

        private string GetElementFolderName(string RawString)
        {
            if (ResourceHelper.IsResourceString(RawString))
            {
                return ResourceHelper.ParseResourceKeyFromRawString(RawString);
            }
            else
            {
                return RawString;
            }
        }

        private void btnPageGeneral_DefaultResourceFilePick_Click(object sender, EventArgs e)
        {
            try
            {
                if (!CheckForPendingResourceChanges())
                    return;

                try
                {
                    using (DialogSelectResource dialog = new DialogSelectResource(m_feature_folder, false, this.DefaultResourceFile))
                    {
                        DialogResult res = dialog.ShowDialog(this);
                        if (res == DialogResult.OK && !string.IsNullOrEmpty(dialog.ResourceFileName))
                        {
                            this.DefaultResourceFile = dialog.ResourceFileName;
                        }
                    }
                }
                finally
                {
                    InvalidateResourceCache();

                    grdPageElements_Properties.Refresh();
                    grdPageGeneral_MainInfo.Refresh();
                }

            }
            catch (Exception ex)
            {
                DialogError.ShowError(ex, false);
            }
        }

        private void btnPageGeneral_DefaultResourceFileNew_Click(object sender, EventArgs e)
        {
            try
            {
                if (!CheckForPendingResourceChanges())
                    return;

                try
                {
                    using (DialogSelectResource dialog = new DialogSelectResource(m_feature_folder, true, this.DefaultResourceFile))
                    {
                        DialogResult res = dialog.ShowDialog(this);
                        if (res == DialogResult.OK && !string.IsNullOrEmpty(dialog.ResourceFileName))
                        {
                            this.DefaultResourceFile = dialog.ResourceFileName;
                        }
                    }
                }
                finally
                {
                    InvalidateResourceCache();

                    grdPageElements_Properties.Refresh();
                    grdPageGeneral_MainInfo.Refresh();
                }

            }
            catch (Exception ex)
            {
                DialogError.ShowError(ex, false);
            }
        }

        private void InvalidateResourceCache()
        {
            foreach (IPropertySheet sheet in lstPageElements_ContainingElements.Items)
            {
                sheet.InvalidateResourceChache();
                sheet.SetNewDefaultResourceFile(this.DefaultResourceFile);
            }

            m_main_info.InvalidateResourceChache();
            m_main_info.SetNewDefaultResourceFile(this.DefaultResourceFile);
        }

        private void ImportContentType()
        {
            if (lstPageElements_ContainingElements.SelectedItem == null)
                return;


            PropSheetContentType prop_sheet = lstPageElements_ContainingElements.SelectedItem as PropSheetContentType;
            if (prop_sheet == null)
                throw new Exception("The selected object is not a content type.");

            string msg = "All data entered for this content type will be overwritten. Do you want to continue?";
            if (MessageBox.Show(msg, "Prompt", MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button2) != DialogResult.OK)
                return;

            string element_file_name = prop_sheet.ElementFileName;
            int element_id = prop_sheet.ElementInfo.ID;

            using (DialogSharePointExplorer explorer = new DialogSharePointExplorer())
            {
                explorer.ShowContentTypes = true;
                explorer.ShowContentTypeGroups = true;
                explorer.ShowLists = false;
                explorer.UseWOW64BitCompatibleMode = Common.CheckIf32bitOn64();
                explorer.Message = "Pick a content type to import.";

                DialogResult res = explorer.ShowDialog(this);
                if (res != DialogResult.OK)
                    return;

                if (!explorer.UseWOW64BitCompatibleMode)
                {
                    SPContentType ct = explorer.SelectedContentType;
                    if (ct != null)
                    {

                        m_feature_manager.RemoveElement(element_id, false);
                        
                        
                        bool importFieldDefinitions = false;
                        string msg2 = "Should all field definitions that belongs to this contentype be imported too?";
                        DialogResult res2 = MessageBox.Show(msg2, "Prompt", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
                        if (res2 == DialogResult.Yes)
                        {
                            importFieldDefinitions = true;
                        }

                        XmlDocument xmldoc = new XmlDocument();
                        xmldoc.LoadXml("<ContentType/>");

                        XmlElement el = xmldoc.DocumentElement;

                        el.SetAttribute("ID", ct.Id.ToString());
                        el.SetAttribute("Name", ct.Name);
                        el.SetAttribute("Description", ct.Description);
                        el.SetAttribute("Group", ct.Group);


                        ElementInfo el_info = m_feature_manager.AddElement(element_file_name, el.OuterXml);
                        prop_sheet = new PropSheetContentType(this.DefaultResourceFile, m_feature_folder, el_info.XmlElementNode);
                        prop_sheet.ElementFileName = el_info.ElementFileName;
                        prop_sheet.ElementInfo = el_info;

                        SPContentType ct_parent = ct.Parent;
                        Hashtable remove_fields = new Hashtable();

                        if (ct_parent != null)
                        {
                            while (ct_parent.Name != "System")
                            {
                                foreach (SPField fld in ct_parent.Fields)
                                    if (!remove_fields.ContainsKey(fld.Id))
                                        remove_fields.Add(fld.Id, true);

                                ct_parent = ct_parent.Parent;

                            }
                        }

                        List<XmlElement> fields_to_add = new List<XmlElement>();
                        XmlElement xe_fieldrefs = prop_sheet.ElementInfo.XmlDoc.CreateElement("FieldRefs", Common.C_MS_SHAREPOINT_XMLNS);

                        foreach (SPField fld in ct.Fields)
                        {
                            if (remove_fields.ContainsKey(fld.Id))
                                continue;

                            XmlElement xe_fieldref = prop_sheet.ElementInfo.XmlDoc.CreateElement("FieldRef", Common.C_MS_SHAREPOINT_XMLNS);
                            xe_fieldref.SetAttribute("ID", fld.Id.ToString());
                            xe_fieldref.SetAttribute("Name", fld.InternalName);

                            xe_fieldrefs.AppendChild(xe_fieldref);

                            XmlDocument field_schema_xml = new XmlDocument();
                            field_schema_xml.LoadXml(fld.SchemaXml);

                            XmlElement new_field_xml = prop_sheet.ElementInfo.XmlDoc.CreateElement("Field", Common.C_MS_SHAREPOINT_XMLNS);
                            foreach (XmlAttribute attr in field_schema_xml.DocumentElement.Attributes)
                            {
                                if (attr.Name == "Customization" ||
                                    attr.Name == "Version")
                                    continue;

                                new_field_xml.SetAttribute(attr.Name, attr.Value);
                            }


                            if (importFieldDefinitions)
                            {
                                el_info = m_feature_manager.AddElement("Fields.xml", new_field_xml.OuterXml);

                                PropSheetField prop_sheet_field = new PropSheetField(this.DefaultResourceFile, m_feature_folder, el_info.XmlElementNode);
                                prop_sheet_field.ElementFileName = el_info.ElementFileName;
                                prop_sheet_field.ElementInfo = el_info;

                                lstPageElements_ContainingElements.Items.Add(prop_sheet_field);
                            }
                        }

                        prop_sheet.ElementInfo.XmlElementNode.AppendChild(xe_fieldrefs);


                        lstPageElements_ContainingElements.Items[lstPageElements_ContainingElements.SelectedIndex] = prop_sheet;
                        grdPageElements_Properties.SelectedObject = prop_sheet;
                        grdPageElements_Properties.Refresh();

                    }
                    else
                    {
                        msg = "No content type selected.";
                        MessageBox.Show(msg, "Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                        return;
                    }
                }
                else
                {
                    string xml = explorer.GetContentTypeDataForWOW64();
                    if (string.IsNullOrEmpty(xml))
                    {
                        msg = "No content type selected.";
                        MessageBox.Show(msg, "Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                        return;
                    }

                    XmlDocument xmldoc = new XmlDocument();
                    xmldoc.LoadXml(xml);

                    XmlElement el = xmldoc.GetElementsByTagName("ContentType")[0] as XmlElement;

                    m_feature_manager.RemoveElement(element_id, false);

                    ElementInfo el_info = m_feature_manager.AddElement(element_file_name, el.OuterXml);
                    prop_sheet = new PropSheetContentType(this.DefaultResourceFile, m_feature_folder, el_info.XmlElementNode);
                    prop_sheet.ElementFileName = el_info.ElementFileName;
                    prop_sheet.ElementInfo = el_info;

                    lstPageElements_ContainingElements.Items[lstPageElements_ContainingElements.SelectedIndex] = prop_sheet;
                    grdPageElements_Properties.SelectedObject = prop_sheet;
                    grdPageElements_Properties.Refresh();

                    string msg2 = "Should all field definitions that belongs to this contentype be imported too?";
                    DialogResult res2 = MessageBox.Show(msg2, "Prompt", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
                    if (res2 == DialogResult.Yes)
                    {
                        foreach (XmlNode node in xmldoc.GetElementsByTagName("Field"))
                        {
                            XmlElement el2 = node as XmlElement;
                            if (el2 == null)
                                continue;

                            List<XmlAttribute> list = new List<XmlAttribute>();
                            foreach (XmlAttribute attr in el2.Attributes)
                            {
                                if (attr.Name == "Customization" ||
                                    attr.Name == "Version")
                                {
                                    list.Add(attr);
                                }
                            }
                            foreach (XmlAttribute attr in list)
                                el2.RemoveAttributeNode(attr);


                            el_info = m_feature_manager.AddElement("Fields.xml", el2.OuterXml);

                            PropSheetField prop_sheet_field = new PropSheetField(this.DefaultResourceFile, m_feature_folder, el_info.XmlElementNode);
                            prop_sheet_field.ElementFileName = el_info.ElementFileName;
                            prop_sheet_field.ElementInfo = el_info;

                            lstPageElements_ContainingElements.Items.Add(prop_sheet_field);
                        }
                    }
                }
            }

        }

        private void btnPageElements_ImportContentType_Click(object sender, EventArgs e)
        {
            try
            {
                ImportContentType();

            }
            catch (Exception ex)
            {
                DialogError.ShowError(ex, false);
            }
        }

        private void SaveAllPendingResourceChanges()
        {
            foreach (IPropertySheet sheet in lstPageElements_ContainingElements.Items)
            {
                if (sheet.HasUnsavedResourceChanges)
                {
                    sheet.SaveChanges();
                }
            }

            if (m_main_info.HasUnsavedResourceChanges)
                m_main_info.SaveChanges();
        }

        private bool HasPendingResourceChanges()
        {
            bool ret = false;
            foreach (IPropertySheet sheet in lstPageElements_ContainingElements.Items)
            {
                if (sheet.HasUnsavedResourceChanges)
                {
                    ret = true;
                    break;
                }
            }

            if (m_main_info.HasUnsavedResourceChanges)
                ret = true;

            return ret;
        }

        private void btnPageElements_PickResource_Click(object sender, EventArgs e)
        {
            try
            {
                if (grdPageElements_Properties.SelectedObject == null)
                    return;

                if (grdPageElements_Properties.SelectedGridItem.PropertyDescriptor.IsReadOnly)
                    return;

                grdPageElements_Properties.Focus();

                GridItem item = grdPageElements_Properties.SelectedGridItem;
                object o = grdPageElements_Properties.SelectedObject;

                string name = o.ToString();
                /*
                if (o is PropSheetContentType)
                    name = (o as PropSheetContentType).Name.RawString;
                else if (o is PropSheetCustomAction)
                    name = (o as PropSheetCustomAction).Title.RawString;
                else if (o is PropSheetField)
                    name = (o as PropSheetField).Name;
                else if (o is PropSheetListInstance)
                    name = (o as PropSheetListInstance).Title.RawString;
                else if (o is PropSheetListTemplate)
                    name = (o as PropSheetListTemplate).Name;
                else if (o is PropSheetModule)
                    name = (o as PropSheetModule).Name;

                if (name == string.Empty)
                {
                    name = (o as IPropertySheet).ElementInfo.ElementName + (o as IPropertySheet).ElementInfo.ID.ToString();
                }
                */

                name = name.Replace(" ", "_").Replace("<","").Replace(">","");

                PickResource(grdPageElements_Properties, item, "Element_" + name);

            }
            catch (Exception ex)
            {
                DialogError.ShowError(ex, false);
            }
        }

        private void btnPageGeneral_PickResource_Click(object sender, EventArgs e)
        {
            try
            {
                if (grdPageGeneral_MainInfo.SelectedObject == null)
                    return;

                if (grdPageGeneral_MainInfo.SelectedGridItem.PropertyDescriptor.IsReadOnly)
                    return;

                grdPageGeneral_MainInfo.Focus();

                GridItem item = grdPageGeneral_MainInfo.SelectedGridItem;

                PickResource(grdPageGeneral_MainInfo, item, "Feature");

            }
            catch (Exception ex)
            {
                DialogError.ShowError(ex, false);
            }
        }

        private bool CheckForPendingResourceChanges()
        {

            if (HasPendingResourceChanges())
            {
                bool bSave = true;

                if (!Connect.S_Resources_Ask_before_save)
                {
                    using (DialogYesNoRepeatable dialog = new DialogYesNoRepeatable())
                    {
                        dialog.DialogMessage = "There are unsaved resource changes made which will be discarded if not saved before opening the editor. Do you want to save them before opening the editor?";
                        dialog.DefaultButtonSelect = true;
                        dialog.CheckBoxText = "If answering yes, resources will be saved as needed without asking in the future.";

                        DialogResult result = dialog.ShowDialog();
                        if (result == DialogResult.Cancel)
                            return false;

                        Connect.S_Resources_Ask_before_save = dialog.RepeatAction && (result == DialogResult.Yes);

                        bSave = (result != DialogResult.No);
                    }
                }

                if (bSave)
                {
                    SaveAllPendingResourceChanges();
                }

            }

            return true;

        }

        private void PickResource(PropertyGrid Grid, GridItem Property, string SuggestedNamePrefix)
        {
            if (!CheckForPendingResourceChanges())
                return;


            if (SuggestedNamePrefix == null)
            {
                string default_res_file = string.IsNullOrEmpty(m_resource_editor_last_used_file) ? this.DefaultResourceFile : m_resource_editor_last_used_file;

                using (DialogResourceEditor dialog = new DialogResourceEditor(m_feature_folder, default_res_file, null))
                {
                    dialog.Text = "Resource editor";
                    DialogResult result = dialog.ShowDialog(this);

                    m_resource_editor_last_used_file = dialog.SelectedResourceFile;
                }

                InvalidateResourceCache();

                grdPageElements_Properties.Refresh();
                grdPageGeneral_MainInfo.Refresh();
            }
            else
            {
                string field = Property.PropertyDescriptor.Name;
                ResourceStringContainer res_container = Property.Value as ResourceStringContainer;

                string raw_string = res_container.RawString;
                string value = null;

                if (ResourceHelper.IsResourceString(raw_string))
                {
                    string msg = "Do you want to replace this fields resource bindings?";
                    if (MessageBox.Show(msg, "Prompt", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button2) != DialogResult.Yes)
                        return;
                }

                try
                {
                    string s = "$Resources:" + SuggestedNamePrefix + "_" + field;

                    using (DialogResourceEditor dialog = new DialogResourceEditor(m_feature_folder, this.DefaultResourceFile, s))
                    {
                        dialog.Text = "Select a resource to bind to the property " + Property.PropertyDescriptor.Name;    
                        DialogResult result = dialog.ShowDialog(this);

                        m_resource_editor_last_used_file = dialog.SelectedResourceFile;

                        if (result == DialogResult.OK && !string.IsNullOrEmpty(dialog.ResourceString))
                        {
                            value = dialog.ResourceString;
                        }
                    }

                    if (value != null)
                    {
                        InvalidateResourceCache();

                        res_container = new ResourceStringContainer(value, this.DefaultResourceFile, m_feature_folder);
                        Property.PropertyDescriptor.SetValue(Grid.SelectedObject, res_container);

                        if (Grid.Name == "grdPageElements_Properties")
                        {
                            if (lstPageElements_ContainingElements.SelectedIndex != -1)
                                lstPageElements_ContainingElements.Items[lstPageElements_ContainingElements.SelectedIndex] = Grid.SelectedObject;

                            lstPageElements_ContainingElements.Refresh();
                        }
                    }

                }
                catch
                {
                    InvalidateResourceCache();
                    throw;

                }
                finally
                {
                    Grid.Refresh();
                    Property.Select();
                }



            }
        }

        private void btnResourceEditor_Click(object sender, EventArgs e)
        {
            try
            {
                PropertyGrid grid = null;
                if (tabControl.SelectedTab.Name == "tabPageGeneral")
                    grid = grdPageGeneral_MainInfo;
                else if (tabControl.SelectedTab.Name == "tabPageElements")
                    grid = grdPageElements_Properties;

                GridItem item = null;
                if (grid != null && grid.SelectedGridItem != null)
                {
                    if (grid.SelectedGridItem.Value is ResourceStringContainer)
                        item = grid.SelectedGridItem;
                }

                PickResource(grid, item, null);

            }
            catch (Exception ex)
            {
                DialogError.ShowError(ex, false);
            }
        }

        private struct ValidationMessageInfo
        {
            public string Message;
            public bool CanContinue;

            public ValidationMessageInfo(string Message, bool CanContinue)
            {
                this.Message = Message;
                this.CanContinue = CanContinue;
            }
        }

        private bool ValidateForm(bool noPrompt)
        {
            List<ValidationMessageInfo> msg_list = new List<ValidationMessageInfo>();

            try
            {
                Guid g = new Guid(FeatureID);
            }
            catch
            {
                msg_list.Add(new ValidationMessageInfo("Feature ID is invalid.", false));
            }

            if (m_main_info.Scope == SPFeatureScope.ScopeInvalid)
            {
                msg_list.Add(new ValidationMessageInfo("Feature scope is invalid.", false));
            }

            foreach (object prop_sheet in lstPageElements_ContainingElements.Items)
            {
                if (prop_sheet is PropSheetContentType)
                {
                    PropSheetContentType sheet = prop_sheet as PropSheetContentType;
                    if (string.IsNullOrEmpty(sheet.ID))
                    {
                        string s = sheet.Name.RawString;
                        if (string.IsNullOrEmpty(sheet.Name.RawString))
                            s = "(no name)";

                        msg_list.Add(new ValidationMessageInfo(string.Format(@"Content type '{0}' has invalid ID.", s), false));
                    }

                    if (string.IsNullOrEmpty(sheet.Name.RawString))
                    {
                        msg_list.Add(new ValidationMessageInfo(string.Format(@"Content type '{0}' has invalid name.", sheet.ID), true));
                    }
                }

                else if (prop_sheet is PropSheetField)
                {
                    PropSheetField sheet = prop_sheet as PropSheetField;

                    try
                    {
                        Guid g = new Guid(sheet.ID);
                    }
                    catch
                    {
                        string s = sheet.Name;
                        if (string.IsNullOrEmpty(sheet.Name))
                            s = "(no name)";

                        msg_list.Add(new ValidationMessageInfo(string.Format(@"Field '{0}' has invalid ID.", s), false));
                    }

                    if (string.IsNullOrEmpty(sheet.Name))
                    {
                        msg_list.Add(new ValidationMessageInfo(string.Format(@"Field '{0}' has invalid name.", sheet.ID), true));
                    }

                    if (string.IsNullOrEmpty(sheet.Type))
                    {
                        msg_list.Add(new ValidationMessageInfo(string.Format(@"Field '{0}' has invalid field type.", sheet.ID), true));
                    }
                }

                else if (prop_sheet is PropSheetListInstance)
                {
                    PropSheetListInstance sheet = prop_sheet as PropSheetListInstance;
                    if (string.IsNullOrEmpty(sheet.Url.RawString))
                    {
                        string s = sheet.Title.RawString;
                        if (string.IsNullOrEmpty(sheet.Title.RawString))
                            s = "(no name)";

                        msg_list.Add(new ValidationMessageInfo(string.Format(@"List instance '{0}' has invalid URL.", s), false));
                    }

                    if (string.IsNullOrEmpty(sheet.TemplateType))
                    {
                        msg_list.Add(new ValidationMessageInfo(string.Format(@"List instance '{0}' has invalid template type.", sheet.Url.GetValue(null)), true));
                    }
                }

                else if (prop_sheet is PropSheetListTemplate)
                {
                    PropSheetListTemplate sheet = prop_sheet as PropSheetListTemplate;
                    if (string.IsNullOrEmpty(sheet.Name))
                    {
                        msg_list.Add(new ValidationMessageInfo(string.Format(@"List template '{0}' has invalid name.", sheet.Type.ToString()), false));
                    }

                    if (string.IsNullOrEmpty(sheet.OriginalType.TemplateName) && sheet.ElementInfo.New)
                    {
                        msg_list.Add(new ValidationMessageInfo(string.Format(@"List template '{0}' has invalid built-in template type to copy from.", sheet.Name.ToString()), false));
                    }
                }

                else if (prop_sheet is PropSheetModule)
                {
                    PropSheetModule sheet = prop_sheet as PropSheetModule;
                    if (string.IsNullOrEmpty(sheet.Name))
                    {
                        msg_list.Add(new ValidationMessageInfo(string.Format(@"One module element has invalid name."), false));
                    }
                }
            }


            if (msg_list.Count > 0)
            {
                foreach (ValidationMessageInfo info in msg_list)
                {
                    if (noPrompt)
                    {
                        if (!info.CanContinue)
                            return false;
                    }
                    else
                    {
                        if (info.CanContinue)
                        {
                            DialogResult result = MessageBox.Show(info.Message + " Do you want to continue?", "Validation error.", MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button2);
                            if (result == DialogResult.Cancel)
                                return false;
                        }
                        else
                        {
                            MessageBox.Show(info.Message, "Validation error.", MessageBoxButtons.OK, MessageBoxIcon.Error);
                            return false;
                        }
                    }
                }
            }

            return true;
        }

        private void btnPageActivationDep_add_Click(object sender, EventArgs e)
        {
            try
            {
                if (string.IsNullOrEmpty(cboPageActivationDep_FeatureToAdd.Text))
                    return;

                string feature_id_str;
                string name;
                string[] arr = cboPageActivationDep_FeatureToAdd.Text.Trim().Split(':');

                if (arr.Length > 1)
                {
                    name = arr[0].Trim();
                    feature_id_str = arr[1].Trim().ToUpper();
                }
                else
                {
                    name = "(feature not in project)";
                    feature_id_str = arr[0].Trim().ToUpper();
                }

                Guid feature_id;
                try
                {
                    feature_id = new Guid(feature_id_str);
                }
                catch
                {
                    string msg = "The id is not in GUID format.";
                    MessageBox.Show(msg, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }

                if (m_features_in_project.ContainsKey(feature_id))
                    name = m_features_in_project[feature_id];

                foreach (string s in lstPageActivationDep_List.Items)
                {
                    string[] arr2 = s.Split(':');
                    if (new Guid(arr2[1].Trim().ToUpper()) == feature_id)
                    {
                        string msg = "The id is already in the list.";
                        MessageBox.Show(msg, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        return;
                    }
                }

                lstPageActivationDep_List.Items.Add(name + ":" + feature_id_str);
                m_feature_manager.ActivationDependencies.Add(feature_id);

                cboPageActivationDep_FeatureToAdd.Text = string.Empty;

            }
            catch (Exception ex)
            {
                DialogError.ShowError(ex, false);
            }
        }

        private void btnPageActivationDep_delete_Click(object sender, EventArgs e)
        {
            try
            {
                string s = lstPageActivationDep_List.SelectedItem as string;

                if (s != null)
                {

                    string msg = "Do you want to remove the feature '" + s + "' from the activation dependencies list?";
                    DialogResult result = MessageBox.Show(msg, "Error", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button2);

                    if (result == DialogResult.Yes)
                    {
                        string[] arr = s.Split(':');

                        lstPageActivationDep_List.Items.RemoveAt(lstPageActivationDep_List.SelectedIndex);
                        m_feature_manager.ActivationDependencies.Remove(new Guid(arr[1].Trim().ToUpper()));
                    }
                }

            }
            catch (Exception ex)
            {
                DialogError.ShowError(ex, false);
            }
        }
    }
}
